/* 工厂模式（factory method）,定义一个创建产品的工厂接口，将产品对象的实现推迟到具体的工厂中.
工厂模式是对简单模式的升级，将实例的过程推迟到具体的工厂中 */

#include <iostream>
#include <memory>

using namespace std;

// 算法抽象接口类
class Segment {

public:
	virtual void print_result() = 0;
};

#pragma region SegmentThreshold

class SegmentThreshold : public Segment
{
public:
	void print_result();

};

void SegmentThreshold::print_result()
{
	cout << "Using threshold to segment." << endl;
}

#pragma endregion

#pragma region SegmentGrowing

class SegmentGrowing : public Segment
{
public:
	void print_result();
};

void SegmentGrowing::print_result()
{
	cout << "Using growing to segment."<< endl;
}

#pragma endregion

// 工厂抽象类
class Factory
{
public:
	virtual Segment* set_alg() = 0;

private:

};

#pragma region ThresholdFactory

class ThresholdFactory :public Factory
{
public:
	Segment* set_alg();

};

Segment* ThresholdFactory::set_alg()
{
	return new SegmentThreshold();
}

#pragma endregion


#pragma region GrowingFactory

class GrowingFactory : public Factory
{
public:
	Segment* set_alg();

};

Segment* GrowingFactory::set_alg()
{
	return new SegmentGrowing();
}
#pragma endregion


int main(int argc, char const *argv[])
{
	unique_ptr<Factory> factory_ptr = nullptr;
	unique_ptr<Segment> segment_ptr = nullptr;

	// 实际应用中，只需要修改这行代码就可以切换不同的算法，
	// 前后的代码都不需要修改，减少了代码的修改量。
	factory_ptr.reset(new ThresholdFactory());

	segment_ptr.reset(factory_ptr->set_alg());
	segment_ptr->print_result();
	
	cout<<"\n\nChange alg..."<<endl;
	factory_ptr.reset(new GrowingFactory());
	segment_ptr.reset(factory_ptr->set_alg());
	segment_ptr->print_result();

	return 0;
}
